const WxPay = require("wechatpay-node-v3");
const axios = require("axios");
const crypto = require("../crypto");

module.exports = class WechatPayUtil extends WxPay {
  constructor(config, context) {
    super(config);
    this.ctx = context;
    this.cfg = context.config.wxpay;
  }

  async order(data, outTradeNo, extendParams) {
    const prepay_id = await this._getPrePayId(data, outTradeNo, extendParams);
    if (prepay_id) {
      try {
        return this._order(this.cfg.appId, prepay_id);
      } catch (error) {
        console.error("_wechatpay===>", error);
      }
    }
  }

  uuid() {
    return crypto.uuid().replaceAll("-", "");
  }

  async _getPrePayId(data, outTradeNo, extendParams) {
    // 参数介绍请看 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml
    const params = {
      appid: this.cfg.appId, // 应用ID
      mchid: this.cfg.mchid, // 直连商户号
      description: data.subject, // 商品描述
      out_trade_no: outTradeNo, // 商户订单号
      notify_url: this.cfg.notifyUrl, // 回调url通知地址
      // 订单金额单位为分
      amount: {
        total: data.amount,
      },
      attach: JSON.stringify(extendParams),
      // time_expire: moment().add(30, "m"), // 交易结束时间（可选）指定30分钟内付款
    };
    const nonce_str = this.uuid(); // 随机字符串
    const timestamp = Math.floor(new Date().getTime() / 1000) + ""; // 时间戳
    const url = "/v3/pay/transactions/app";

    // 获取签名 如果是get请求则不需要params参数拼接在url上
    // 例如/v3/pay/transactions/id/12177525012014?mchid=1230000109
    const signature = this.getSignature(
      "POST",
      nonce_str,
      timestamp,
      url,
      JSON.stringify(params)
    );

    // 获取头部authorization 参数
    const authorization = this.getAuthorization(
      nonce_str,
      timestamp,
      signature
    );

    const headers = {
      Accept: "application/json",
      "Content-Type": "application/json",
      "User-Agent": this.ctx.headers["user-agent"],
      Authorization: authorization,
    };
    const subUrl = `https://api.mch.weixin.qq.com${url}`;
    let prepay_id;
    try {
      prepay_id = await axios
        .post(subUrl, params, {
          headers,
        })
        .then((res) => res.data.prepay_id);
    } catch (error) {
      console.error("_wxGetPrePayId===>", error);
    }
    return prepay_id;
  }

  _order(appId, prepay_id) {
    // 获取到prepay_id后生成签名相见：顺序不能错乱，且最后必须要有一个\n
    // https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_4.shtml#menu1
    // 应用id
    // 时间戳
    // 随机字符串
    // 预支付交易会话ID
    // const timeStamp = new Date().getTime().toString();
    const timeStamp = Math.floor(new Date().getTime() / 1000) + ""; // 时间戳
    const nonceStr = this.uuid();
    const signStr = `${appId}\n${timeStamp}\n${nonceStr}\n${prepay_id}\n`;
    const sign = this.sign(signStr);
    return {
      sign,
      timeStamp,
      nonceStr,
      prepay_id,
    };
  }
};
